from pywinauto import findwindows
import warnings
import time
from pywinauto import Application
import json

warnings.filterwarnings("ignore", category=UserWarning, module="pywinauto")


def start(path, backend="win32"):
    Application(backend).start(path)


# 获取目标控件
def get_element_by_window(window, target, timeout=30, is_exists=True, is_enabled=True):
    try:
        for i in range(timeout):
            element = window.child_window(**target)
            if element.exists() and element.is_visible():
                if is_enabled:
                    element.wait('enabled', timeout=timeout)
                return element
        time.sleep(1)
        if is_exists:
            raise Exception(
                "获取windows页面元素超时:%s" % (json.dumps(target, ensure_ascii=False))
            )
        return None
    except Exception as e:
        raise Exception(
            "获取windows页面元素出错target:%s error: %s"
            % (json.dumps(target, ensure_ascii=False), e)
        )


# 根据handle获取窗口
def get_window_by_handle(handle, backend="win32"):
    app = Application(backend).connect(handle=handle)
    return app.window(handle=handle)


# 根据title与窗口目标控件返回对应窗口
def get_window(title, target=None, timeout=30, is_exists=True, backend="win32"):
    try:
        for i in range(timeout):
            windows = findwindows.find_elements(
                title_re=title, backend=backend, visible_only=True
            )
            window_list = list(
                map(lambda item: get_window_by_handle(item.handle, backend), windows)
            )
            if target and len(window_list) > 0:
                target_window_list = []
                for window in window_list:
                    if get_element_by_window(
                        window, target, timeout=1, is_exists=False
                    ):
                        target_window_list.append(window)
                window_list = target_window_list
            if len(window_list) == 1:
                return window_list[0]
            time.sleep(1)
        if is_exists:
            raise Exception(
                "获取%s的window出错 该标题下 有%d个window" % (title, len(window_list))
            )
        return None
    except Exception as e:
        raise Exception(e)


# 根据指定控件（title指定）偏移量获取目标控件
def get_element_by_offset(window, title, offset, timeout=30, is_exists=True):
    try:
        children = window.children()
        for i in range(len(children)):
            if children[i].window_text() == title:
                element_handle = children[i + offset].handle
                element = window.child_window(handle=element_handle)
                if element.exists() and element.is_visible():
                    element.wait('enabled', timeout=timeout)
                    return element
        if is_exists:
            raise Exception("获取不到windows页面元素:%s" % (title))
        return None
    except Exception as e:
        raise Exception("获取windows页面元素错误title:%s error:%s" % (title, e))

def get_element_by_deep(window, title, offset, timeout=30, is_exists=True):
    try:
        element = get_deep(window.children(), title, offset, timeout)
        if element:
            return element
        if is_exists:
            raise Exception("获取不到windows页面元素:%s" % (title))
        return None
    except Exception as e:
        raise Exception("获取windows页面元素错误title:%s error:%s" % (title, e))

def get_deep(children, title, offset, timeout):
    for i in range(len(children)):
        if children[i].window_text() == title:
            return children[i + offset]
        element = get_deep(children[i].children(), title, offset, timeout)
        if(element):
            return element
    return None

# 获取元素（多选一）
def get_elements_by_window(window, targets, timeout=30, is_enabled=True):
    try:
        elements = []
        for i in range(timeout):
            elements = []
            for item in targets:
                elements.append(
                    get_element_by_window(
                        window, item, timeout=1, is_exists=False, is_enabled=is_enabled
                    )
                )
            if any(x is not None for x in elements):
                return elements
            time.sleep(1)
        return elements
    except Exception as e:
        raise Exception("获取windows页面元素错误error:%s" % e)


# 获取窗口（多选一）
def get_windows(targets, timeout=30):
    try:
        windows = []
        for i in range(timeout):
            windows = []
            for item in targets:
                windows.append(
                    get_window(
                        item["title"],
                        item.get("target", None),
                        timeout=1,
                        is_exists=False,
                    )
                )
            if any(x is not None for x in windows):
                return windows
            time.sleep(1)
        return windows
    except Exception as e:
        raise Exception("获取windows页面错误error:%s" % e)
